using System;
using System.Collections;
using System.Data;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.COI;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Policy;
using PHSRAG.Security.Enumerations;
using PHSRAG.Utility;

namespace PHSRAG.Insight21.Admin
{
    /// <summary>
    /// The AdminUserModuleAccess page allows the logged in user to view/edit 
    /// a user's access to the Insight application's modules.
    /// </summary>
    public partial class AdminUserModuleAccess : BasePage
    {
        #region Constants

        private const string ApplicationUserTableName = "ApplicationUser";
        private const string EditModeImageURL = "../Images/b_edit.gif";
        private const string ModuleBitmask = "ModuleBitmask";
        private const string SaveModeImageURL = "../Images/b_save.gif";

        #endregion

        #region Instance variables (Protected)

        /// <summary>Provides sub navigation functionality within the Admin module's user management pages. </summary>
        protected AdminUserManagementSubNavigation adminUserDetailsSubNavigation;

        #endregion

        #region Instance variables (Private)

        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;

        #endregion

        #region Private Properties

        /// <summary>
        /// Gets the relevant user object from the cache if there is one otherwise loads 
        /// a new one based on the cached personID and cache's it.
        /// </summary>
        private new User User
        {
            get
            {
                User user = cachePolicy.GetCachedObject(User.CacheKey) as User;

                Hashtable h = (Hashtable) pageCachePolicy.GetCachedObject(Keys.IncomingDataKey);
                int personId = (int) h[Keys.PersonIdKey];

                if (user == null || (user.PersonId != personId))
                {
                    user = new User(cachePolicy);
                    user.Load(DataAccess.GetConnectionString(), personId);
                    user.Cache();
                }

                return user;
            }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Occurs when the server control is loaded into the Page object.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            adminUserManagementSubNavigation.SelectedLink = AdminUserManagementSubNavigation.AdminModuleAccessCommand;

            if (!IsPostBack)
            {
                try
                {
                    breadCrumb.Add("Module Access", "AdminUserModuleAccess.aspx", Settings.GetKeyValue("BreadCrumb.Admin.AdminUserModuleAccessPageLevel", 2));

                    lastName.Text = User.LastName;
                    firstName.Text = User.FirstName;
                    userName.Text = User.Username;
                    organization.Text = User.Organization;

                    editSave.ImageUrl = (User.IsRegistered) ? EditModeImageURL : SaveModeImageURL;

                    dataGrid.DataSource = User.ModuleAccess.DetailsForUI;
                    dataGrid.DataBind();

                    if (!User.IsRegistered)
                    {
                        editSave.Visible = false;
                        annunciator.Message = "This user is not registered.";
                    }
                }
                catch (Exception ex)
                {
                    annunciator.Message = ExceptionReport.GetExceptionInfo(ex, false);
                    ExceptionReport.WriteToEventLog("AdminUserModuleAccess", ex, true, ExceptionReport.ReportType.Error);
                }
            }
        }

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        protected void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            adminUserManagementSubNavigation.Reset();
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Initializes components used on the page.
        /// </summary>
        /// <param name="e"></param>
        protected override void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
        }

        #endregion

        #region Handled Events

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                ((CheckBox) (e.Item.Cells[3]).Controls[1]).Checked = Convert.ToBoolean(User.ModuleAccess.Details.Select(String.Format("Name = '{0}'", e.Item.Cells[1].Text))[0]["IsSelected"]);
                ((CheckBox) (e.Item.Cells[3]).Controls[1]).Enabled = false;
            }
        }

        /// <summary>
        /// This is the handler for the event that is fired when the Edit/Save button is clicked.  If
        /// the button's text is "Edit" we are entering edit mode so the checkboxes in the grid that 
        /// were disabled will now get enabled and the button's text toggled to "Save".  Otherwise,
        /// we are in save mode and calculate the module bitmask by adding up all of bitvalues
        /// associated with checked modules.  The application user details are then updated with the 
        /// summed module bitmask and saved.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void OnEditSave(object sender, ImageClickEventArgs e)
        {
            if (editSave.ImageUrl == EditModeImageURL)
            {
                SetModulesCheckBoxEnabled(true);

                editSave.ImageUrl = SaveModeImageURL;
            }
            else
            {
                int moduleBitMask = 0;
                DataTable applicationUserTable = User.ApplicationUserDetail.GetDataContainer().Tables[ApplicationUserTableName];
                DataRow[] rows = User.ModuleAccess.Details.Select(String.Format("IsGrantedViaUI = 0"));

                foreach (DataRow row in rows)
                {
                    if ((Convert.ToInt32(row["BitValue"]) & Convert.ToInt32(applicationUserTable.Rows[0][ModuleBitmask])) > 0)
                    {
                        moduleBitMask += Convert.ToInt32(row["BitValue"]);
                    }
                }

                foreach (DataGridItem item in dataGrid.Items)
                {
                    if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
                    {
                        if (((CheckBox) (item.Cells[3]).Controls[1]).Checked)
                        {
                            moduleBitMask += Convert.ToInt32(item.Cells[0].Text);
                        }
                    }
                }

                //Terminate all COIs if user had COI access earlier and is now being removed
                if ((Convert.ToInt32(applicationUserTable.Rows[0][ModuleBitmask]) & (int) ModuleBit.COI) != 0 &&
                    (moduleBitMask & (int) ModuleBit.COI) == 0)
                {
                    COICollection.TerminateLatestCOI(DataAccess.ConnectionString, User.PersonId);
                }

                applicationUserTable.Rows[0][ModuleBitmask] = moduleBitMask;
                User.ApplicationUserDetail.Save(DataAccess.GetConnectionString());
                User.UnCache();

                SetModulesCheckBoxEnabled(false);
                editSave.ImageUrl = EditModeImageURL;
            }
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Disables/Enables the Module checkbox column in the datagrid based on the passed in 
        /// boolean parameter value.
        /// </summary>
        /// <param name="isEnabled">Indicator used to enable/disable the checkbox column.</param>
        private void SetModulesCheckBoxEnabled(bool isEnabled)
        {
            //toggle to edit mode
            foreach (DataGridItem item in dataGrid.Items)
            {
                if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
                {
                    ((CheckBox) (item.Cells[3]).Controls[1]).Enabled = isEnabled;
                }
            }
        }

        #endregion
    }
}